package gui;

import API_Jung.PopupVertexEdgeMenuMousePlugin;
import API_Jung.MyMouseMenusToDo;
import edu.uci.ics.jung.algorithms.layout.KKLayout;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.visualization.FourPassImageShaper;
import edu.uci.ics.jung.visualization.LayeredIcon;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.EditingModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.EllipseVertexShapeTransformer;
import edu.uci.ics.jung.visualization.decorators.VertexIconShapeTransformer;
import edu.uci.ics.jung.visualization.renderers.DefaultEdgeLabelRenderer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Shape;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.Iterator;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import metodologia.TestNode;
import metodologia.ToDoNode;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.Factory;

public class JanelaSubTestes extends javax.swing.JFrame implements java.io.Serializable {

    private int nodetype, nodecount, nTests, nEdges;
    private DirectedSparseGraph<ToDoNode, String> g;
    private ToDoNode start, end;
    private KKLayout<ToDoNode, String> layout;
    private VisualizationViewer<ToDoNode, String> vv;
    private JScrollPane graphScroll;
    private boolean novo;
    private EditingModalGraphMouse<ToDoNode, String> graphMouse;
    private String nomeDoTeste;
    private boolean abrir;

    /** Creates new form ToDoScreen */
    public JanelaSubTestes(TestNode vertex) {
        initComponents();
        ImageIcon imagemTituloJanela = new ImageIcon(getClass().getResource("/ImageFiles/icon_PW.png"));  
        setIconImage(imagemTituloJanela.getImage());
        this.setLocationRelativeTo(null);
        this.setTitle("PWManager - Conjunto de Etapas: ");
        nomeDoTeste = vertex.toString();
        g = vertex.getG();
        layout = new KKLayout(g);
        layout.setSize(new Dimension(300, 300));
        novo = true;
//        nodetype = 0;
//        nodecount = 0;
        nTests = 1;
        nEdges = 1;
//        graphMouse = null;
        
        createGraphScreen();

        createToolBar();

        this.setMinimumSize(new Dimension(750, 450));
        this.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent we) {
                atualizarPosicaoDosVertices();
            }
        });
        
        
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    }
    
    public void atualizarPosicaoDosVertices() {
                for (Iterator it = g.getVertices().iterator(); it.hasNext();) {
                    ToDoNode object = (ToDoNode) it.next();
                    object.setX(layout.getX(object));
                    object.setY(layout.getY(object));

                }
            }
    
    public void zerarToolbar(boolean bool){
        jToolBar1.setVisible(bool);
        abrir = true;
    }

    public final void createToolBar() {
        this.b_Start.setToolTipText("Add Start");
        this.b_End.setToolTipText("Add End");
        this.buttonGroup1.add(this.b_Start);
        this.buttonGroup1.add(this.b_ToDo);
        this.buttonGroup1.add(this.b_End);
        this.buttonGroup1.setSelected(this.b_Start.getModel(), true);
    }

    public final void createGraphScreen() {
        //JTabbedPane GraphS = new JTabbedPane();

        vv = new VisualizationViewer<ToDoNode, String>(layout);
        vv.setPreferredSize(new Dimension(300, 300));
        vv.setBackground(Color.WHITE);

        // Show vertex and edge labels

        vv.getRenderContext().setVertexLabelTransformer(new Transformer<ToDoNode, String>() {

            @Override
            public String transform(ToDoNode v) {
                switch (v.getType()) {
                    case 0:
                        return "Start";
                    case 1:
                        return "End";
                    case 2:
                        return "List" + " " + v.getCatid();
                }
                return "Start";
            }
        });

        vv.getRenderContext().setEdgeLabelTransformer(new Transformer<String, String>() {

            @Override
            public String transform(String e) {
                return "";
            }
        });

        vv.getRenderContext().setVertexIconTransformer(
                new MyVertexIconTransformer<ToDoNode>());
        vv.getRenderContext().setVertexShapeTransformer(
                new MyVertexIconShapeTransformer<TestNode>(new EllipseVertexShapeTransformer<ToDoNode>()));
        vv.getRenderContext().setEdgeLabelRenderer(new DefaultEdgeLabelRenderer(Color.cyan));
        vv.setVertexToolTipTransformer(vv.getRenderContext().getVertexLabelTransformer());


        Factory<ToDoNode> vertexFactory = new VertexFactory();
        Factory<String> edgeFactory = new EdgeFactory();

        graphMouse = new EditingModalGraphMouse<ToDoNode, String>(vv.getRenderContext(), vertexFactory, edgeFactory);

        PopupVertexEdgeMenuMousePlugin myPlugin = new PopupVertexEdgeMenuMousePlugin();
        // Add some popup menus for the edges and vertices to our mouse plugin.
        JPopupMenu vertexMenu = new MyMouseMenusToDo.VertexMenu2();
        JPopupMenu EdgeMenu = new MyMouseMenusToDo.EdgeMenu2();

        myPlugin.setVertexPopup(vertexMenu);
        myPlugin.setEdgePopup(EdgeMenu);
        graphMouse.remove(graphMouse.getPopupEditingPlugin());  // Removes the existing popup editing plugin

        graphMouse.add(myPlugin);   // Add our new plugin to the mouse

        vv.setGraphMouse(graphMouse);
        vv.addKeyListener(graphMouse.getModeKeyListener());

        graphMouse.setMode(ModalGraphMouse.Mode.EDITING);
        this.jComboBox1.setModel(graphMouse.getModeComboBox().getModel());

         graphScroll = new JScrollPane(vv);
        graphScroll.setSize(this.GraphScreen.getSize());

        //GraphS.addTab(nomeDoTeste + ": Conjunto de Etapas", graphScroll);


        GraphScreen.setLayout(new BorderLayout());
        //GraphScreen.add("Center", GraphS);
        GraphScreen.add("Center", graphScroll);
        Collection<ToDoNode> col = g.getVertices();
        if (!col.isEmpty()) {
            reloadGraphScreen();
        } else {
            vv.repaint();
        }
        
    }

    public final void reloadGraphScreen() {

        layout.setGraph(g);
        for (Iterator it = g.getVertices().iterator(); it.hasNext();) {
            ToDoNode object = (ToDoNode) it.next();
            layout.setLocation(object, new Point2D.Double(object.getX(), object.getY()));
            if (object.getType() == 2) {
                nTests++;
            }
            if(object.getType() == 0) start = object;
        }

        vv.setGraphLayout(layout);
        Factory<ToDoNode> vertexFactory = new VertexFactory();
        Factory<String> edgeFactory = new EdgeFactory();
        graphMouse =
                new EditingModalGraphMouse<ToDoNode, String>(vv.getRenderContext(), vertexFactory, edgeFactory);

        PopupVertexEdgeMenuMousePlugin myPlugin = new PopupVertexEdgeMenuMousePlugin();
        // Add some popup menus for the edges and vertices to our mouse plugin.
        JPopupMenu vertexMenu = new MyMouseMenusToDo.VertexMenu2();

        JPopupMenu EdgeMenu = new MyMouseMenusToDo.EdgeMenu2();

        myPlugin.setVertexPopup(vertexMenu);
        myPlugin.setEdgePopup(EdgeMenu);
        graphMouse.remove(graphMouse.getPopupEditingPlugin());  // Removes the existing popup editing plugin

        graphMouse.add(myPlugin);   // Add our new plugin to the mouse

        vv.setGraphMouse(graphMouse);
        vv.addKeyListener(graphMouse.getModeKeyListener());

        graphMouse.setMode(ModalGraphMouse.Mode.EDITING);
        this.jComboBox1.setModel(graphMouse.getModeComboBox().getModel());
        nEdges = g.getEdgeCount();
        nodecount = g.getVertexCount();

        this.graphScroll.setViewportView(vv);
    }

    public void setG(DirectedSparseGraph<ToDoNode, String> g) {
        this.g = g;
    }
    
    public DirectedSparseGraph<ToDoNode, String> getG(){
        return g;
    }

    public boolean isNovo() {
        return novo;
    }

    public void setNovo(boolean novo) {
        this.novo = novo;
    }
    
    public void setGraphMouse(){
        graphMouse.remove(graphMouse.getPopupEditingPlugin());  // Removes the existing popup editing plugin

        //graphMouse.add(myPlugin);   // Add our new plugin to the mouse

        vv.setGraphMouse(graphMouse);
        vv.addKeyListener(graphMouse.getModeKeyListener());

//        graphMouse.setMode(ModalGraphMouse.Mode.EDITING);
        graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
    }

    public class MyVertexIconTransformer<ToDoNode> implements Transformer<ToDoNode, Icon> {

        @Override
        public Icon transform(ToDoNode n) {
            String[] n2 = n.toString().split("a");
            String[] n3 = n.toString().split("n");

            if (n2.length > 1) {
                Icon icon = new LayeredIcon(new ImageIcon(getClass().getResource("/ImageFiles/StartBall.png")).getImage());
                return icon;
            } else if (n3.length > 1) {
                Icon icon = new LayeredIcon(new ImageIcon(getClass().getResource("/ImageFiles/EndNode.png")).getImage());
                return icon;
            } else {
                for (Iterator it = g.getEdges().iterator(); it.hasNext();) {
                    String edge = (String) it.next();
                    if (g.getEndpoints(edge).getFirst().toString().equals(n.toString()) && g.getEndpoints(edge).getSecond().toString().equals(start.toString())) {
                        Icon icon = new LayeredIcon(new ImageIcon(getClass().getResource("/ImageFiles/targetBall.png")).getImage());
                        return icon;
                    } else if (g.getEndpoints(edge).getSecond().toString().equals(n.toString()) && g.getEndpoints(edge).getFirst().toString().equals(start.toString())) {
                        Icon icon = new LayeredIcon(new ImageIcon(getClass().getResource("/ImageFiles/targetBall.png")).getImage());
                        return icon;
                    }
                }

                Icon icon = new LayeredIcon(new ImageIcon(getClass().getResource("/ImageFiles/TestNode.png")).getImage());
                return icon;
            }
        }
    }

    public static class MyVertexIconShapeTransformer<TestNode> extends VertexIconShapeTransformer<ToDoNode> {

        boolean shapeImages = true;

        public MyVertexIconShapeTransformer(Transformer<ToDoNode, Shape> delegate) {
            super(delegate);
        }
        
        public boolean isShapeImages() {
            return shapeImages;
        }

        public void setShapeImages(boolean shapeImages) {
            shapeMap.clear();
            this.shapeImages = shapeImages;
        }

        public Icon getIcon(ToDoNode n) {
            String[] n2 = n.toString().split("a");
            String[] n3 = n.toString().split("n");
            if (n2.length > 1) {
                Icon icon = new LayeredIcon(new ImageIcon(getClass().getResource("/ImageFiles/StartBall.png")).getImage());
                return icon;
            } else if (n3.length > 1) {
                Icon icon = new LayeredIcon(new ImageIcon(getClass().getResource("/ImageFiles/EndNode.png")).getImage());
                return icon;
            } else {
                Icon icon = new LayeredIcon(new ImageIcon(getClass().getResource("/ImageFiles/TestNode.png")).getImage());
                return icon;
            }
        }

        @Override
        public Shape transform(ToDoNode v) {
            Icon icon = getIcon(v);

            if (icon != null && icon instanceof ImageIcon) {

                Image image = ((ImageIcon) icon).getImage();

                Shape shape = shapeMap.get(image);
                if (shape == null) {
                    if (shapeImages) {
                        shape = FourPassImageShaper.getShape(image, 30);
                    } else {
                        shape = new Rectangle2D.Float(0, 0,
                                image.getWidth(null), image.getHeight(null));
                    }
                    if (shape.getBounds().getWidth() > 0
                            && shape.getBounds().getHeight() > 0) {
                        int width = image.getWidth(null);
                        int height = image.getHeight(null);
                        AffineTransform transform =
                                AffineTransform.getTranslateInstance(-width / 2, -height / 2);
                        shape = transform.createTransformedShape(shape);
                        shapeMap.put(image, shape);
                    }
                }
                return shape;
            } else {
                return delegate.transform(v);
            }
        }
    }

    class VertexFactory implements Factory<ToDoNode> {
        @Override
        public ToDoNode create() {
            switch (nodetype) {
                case 0:
                    System.out.println("nodetype = " + nodetype);
                    if(start == null){
                        start = new ToDoNode(nodecount++, nodetype, 0);
                    }
                    return start;
                case 1:
                    System.out.println("nodetype = " + nodetype);
                    if(end == null){
                        end = new ToDoNode(nodecount++, nodetype, 0);
                    }
                    return end;
                case 2:
                    System.out.println("nodetype = " + nodetype);
                    return new ToDoNode(nodecount++, nodetype, nTests++);
            }
            return new ToDoNode(nodecount++, nodetype, 0);
        }
    }

    class EdgeFactory implements Factory<String> {

        @Override
        public String create() {
            return "" + nEdges++;
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jToolBar1 = new javax.swing.JToolBar();
        jComboBox1 = new javax.swing.JComboBox();
        jLabel2 = new javax.swing.JLabel();
        b_Start = new javax.swing.JToggleButton();
        b_ToDo = new javax.swing.JToggleButton();
        b_End = new javax.swing.JToggleButton();
        GraphScreen = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jToolBar1.setFloatable(false);

        jToolBar1.add(jComboBox1);

        jLabel2.setText("Add:");
        jToolBar1.add(jLabel2);

        b_Start.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ImageFiles/StartBallIcon.png"))); // NOI18N
        b_Start.setFocusable(false);
        b_Start.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        b_Start.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        b_Start.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                b_StartActionPerformed(evt);
            }
        });
        jToolBar1.add(b_Start);

        b_ToDo.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ImageFiles/redBall.png"))); // NOI18N
        b_ToDo.setFocusable(false);
        b_ToDo.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        b_ToDo.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        b_ToDo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                b_ToDoActionPerformed(evt);
            }
        });
        jToolBar1.add(b_ToDo);

        b_End.setIcon(new javax.swing.ImageIcon(getClass().getResource("/ImageFiles/EndNodeIcon.png"))); // NOI18N
        b_End.setFocusable(false);
        b_End.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        b_End.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        b_End.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                b_EndActionPerformed(evt);
            }
        });
        jToolBar1.add(b_End);

        getContentPane().add(jToolBar1, java.awt.BorderLayout.NORTH);

        GraphScreen.setLayout(new java.awt.BorderLayout());
        getContentPane().add(GraphScreen, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void b_EndActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_b_EndActionPerformed
        // TODO add your handling code here:
        nodetype = 1;
    }//GEN-LAST:event_b_EndActionPerformed

    private void b_ToDoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_b_ToDoActionPerformed
        // TODO add your handling code here:
        nodetype = 2;
    }//GEN-LAST:event_b_ToDoActionPerformed

    private void b_StartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_b_StartActionPerformed
        // TODO add your handling code here:
        nodetype = 0;
    }//GEN-LAST:event_b_StartActionPerformed
    /**
     * @param args the command line arguments
     */
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel GraphScreen;
    private javax.swing.JToggleButton b_End;
    private javax.swing.JToggleButton b_Start;
    private javax.swing.JToggleButton b_ToDo;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JComboBox jComboBox1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JToolBar jToolBar1;
    // End of variables declaration//GEN-END:variables
   

}
